import {ShapeManager} from "../shapeManager/ShapeManager";
import {PathInfo} from "../shapeManager/PathInfo";

class ShapeDrawer {
    canvas:any; context:any;
    shapeInfo: ShapeManager | undefined; //当前的图像信息

    readonly PADDING:number = 20;
    startPoint: [number, number] = [0, 0];
    drawingWidth = 10; drawingHeight = 10;
    setCanvas = (can:any) => {
        this.canvas = can;
        this.context = this.canvas.getContext("2d");
    };

    minX = 0; minY = 0; maxX = 0; maxY = 0;

    setShapeToFullScreen = () => {
        let wd = window.devicePixelRatio;
        let canvas = this.canvas;
        const PADDING = this.PADDING;
        this.startPoint = [wd * PADDING, wd * PADDING];
        this.drawingWidth = canvas.width - wd * PADDING * 2;
        this.drawingHeight = canvas.height - wd * PADDING * 2;
        let dWHRatio = this.drawingWidth / this.drawingHeight;

        let sWidth = this.maxX - this.minX, sHeight = this.maxY - this.minY;
        let sWHRatio = sWidth / sHeight;

        if (dWHRatio > sWHRatio) { //高度不变
            this.drawingWidth = this.drawingHeight * sWHRatio;
            this.startPoint[0] = (canvas.width - this.drawingWidth) / 2;
        } else {
            this.drawingHeight = this.drawingWidth / sWHRatio;
            this.startPoint[1] = (canvas.height - this.drawingHeight) / 2;
        }
    };

    setShape = (sp:ShapeManager) => {
        this.shapeInfo = sp;
        let shapeInfo = this.shapeInfo;
        let {sMinX, sMinY, sMaxX, sMaxY} = shapeInfo.GetRangeInfo();
        this.minX = sMinX; this.minY = sMinY;
        this.maxX = sMaxX; this.maxY = sMaxY;
        this.setShapeToFullScreen();
    };

    setMinX = (m:number) => {
        this.minX = m;
    };

    setMinY = (m:number) => {
        this.minY = m;
    };

    setMaxX = (m:number) => {
        this.maxX = m;
    };

    setMaxY = (m:number) => {
        this.maxY = m;
    };

    convertSingleVertexToScreen = (vertex:[number, number]) => {
        let xRatio = (vertex[0] - this.minX) / (this.maxX - this.minX);
        let yRatio = (vertex[1] - this.minY) / (this.maxY - this.minY);
        return [
            this.startPoint[0] + xRatio * this.drawingWidth,
            this.startPoint[1] + (1 - yRatio) * this.drawingHeight
        ];
    };

    markSingleVertex = (vertex:[number, number]) => {
        let point = this.convertSingleVertexToScreen(vertex);
        const context = this.context;

        context.beginPath();
        context.fillStyle = '#FFAAAA';
        context.strokeStyle = 'black';
        context.arc(point[0], point[1], 2 * window.devicePixelRatio, 0, 2 * Math.PI);
        context.fill();
        context.stroke();
    };

    drawPolygon = (polygon:Array<[number, number]>, fill:string) => {
        fill = fill || '#77FFFF';
        const context = this.context;
        context.beginPath();
        for (let p = 0; p < polygon.length; p++) {
            let point = this.convertSingleVertexToScreen(polygon[p]);
            if (p === 0) {
                context.moveTo(point[0], point[1]);
            } else {
                context.lineTo(point[0], point[1]);
            }
        }
        context.closePath();
        context.fillStyle = fill;
        context.fill();
    };

    draw = () => {
        let shapeInfo = this.shapeInfo, context = this.context;
        if (!shapeInfo) return;
        let shapes = shapeInfo.shapeObject, border = shapeInfo.border;

        let DrawSinglePath = (singlePath: PathInfo) => {
            context.beginPath();
            for (let p = 0; p < singlePath.path.length; p++) {
                let vertex = singlePath.path[p];
                let point = this.convertSingleVertexToScreen(vertex);
                if (p === 0) context.moveTo(point[0], point[1]);
                else context.lineTo(point[0], point[1]);
            }

            if (singlePath.closed) {
                context.closePath();
            }

            if (singlePath.fillStyle !== undefined) {
                context.fillStyle = singlePath.fillStyle;
                context.fill();
            }

            if (singlePath.strokeStyle !== undefined) {
                context.strokeStyle = singlePath.strokeStyle;
                context.linewidth = window.devicePixelRatio;
                context.stroke();
            }
        };

        DrawSinglePath(border);
        for (let s = 0; s < shapes.length; s++) {
            let singlePath = shapes[s];
            DrawSinglePath(singlePath);
        }

        let texts = shapeInfo.textObject;
        for (let text of texts) {

            let point = this.convertSingleVertexToScreen([text.x, text.y]);
            context.fillStyle = text.fillColor;
            context.font = `${text.fontSize * window.devicePixelRatio}px Arial`;
            context.fillText(text.text, point[0], point[1]);
        }
    };

    drawImage = (canvas: HTMLCanvasElement | HTMLImageElement) => {
        this.context.drawImage(canvas, this.startPoint[0], this.startPoint[1], this.drawingWidth, this.drawingHeight);
    }
}


export {ShapeDrawer};